/*
 * Copyright (c) 2024 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * @addtogroup HiDebug
 * @{
 *
 * @brief 提供调试功能。
 *
 * 本模块函数可用于获取cpu usage、memory、heap、capture trace等。
 *
 * @since 12
 */

/**
 * @file hidebug.h
 *
 * @brief 定义HiDebug模块的调试功能。
 * @kit PerformanceAnalysisKit
 * @include <hidebug/hidebug.h> 
 * @library libohhidebug.so
 * @syscap SystemCapability.HiviewDFX.HiProfiler.HiDebug
 * @since 12
 */

#ifndef HIVIEWDFX_HIDEBUG_H
#define HIVIEWDFX_HIDEBUG_H

#include <stdint.h>
#include "hidebug_type.h"

#ifdef __cplusplus
extern "C" {
#endif

/**
 * @brief 获取系统的CPU资源占用情况百分比。
 * 注意：由于该接口涉及跨进程通信，耗时较长，建议不要在主线程中直接调用。
 *
 * @return 返回系统CPU资源占用情况百分比。如果返回结果为0，可能的原因是获取失败。
 * @since 12
 */
double OH_HiDebug_GetSystemCpuUsage();

/**
 * @brief 获取进程的CPU使用率百分比。
 * 注意：由于该接口涉及跨进程通信，耗时较长，建议不要在主线程中直接调用。
 *
 * @return 返回进程的CPU使用率百分比。如果返回结果为0，可能因当前应用的CPU使用率过低导致。
 * @since 12
 */
double OH_HiDebug_GetAppCpuUsage();

/**
 * @brief 获取应用所有线程CPU使用情况。
 * 注意：由于该接口涉及跨进程通信，耗时较长，建议不要在主线程中直接调用。
 *
 * @return 返回所有线程CPU使用情况，见{@link HiDebug_ThreadCpuUsagePtr}。
 *         若返回结果为null，可能因未获取到线程相关数据所致。
 * @since 12
 */
HiDebug_ThreadCpuUsagePtr OH_HiDebug_GetAppThreadCpuUsage();

/**
 * @brief 释放线程数据结构。
 *
 * @param threadCpuUsage 应用的所有线程可用CPU使用缓冲区指针，见{@link HiDebug_ThreadCpuUsagePtr}。
 *        传入的参数是要由OH_HiDebug_GetAppThreadCpuUsage()得到的。
 * @since 12
 */
void OH_HiDebug_FreeThreadCpuUsage(HiDebug_ThreadCpuUsagePtr *threadCpuUsage);

/**
 * @brief 获取系统内存信息。
 *
 * @param systemMemInfo 表示指向{@link HiDebug_SystemMemInfo}。
 *        函数调用后，若结构体数据为空，则表明调用失败。
 * @since 12
 */
void OH_HiDebug_GetSystemMemInfo(HiDebug_SystemMemInfo *systemMemInfo);

/**
 * @brief 获取应用程序进程的内存信息。
 * 注意：由于该接口需要读取/proc/{pid}/smaps_rollup节点信息，耗时较长，建议不要在主线程中直接调用。
 *
 * @param nativeMemInfo 表示指向{@link HiDebug_NativeMemInfo}。函数调用后，若结构体数据为空，则表明调用失败。
 * @since 12
 */
void OH_HiDebug_GetAppNativeMemInfo(HiDebug_NativeMemInfo *nativeMemInfo);

/**
 * @brief 获取应用程序进程的内存信息，该接口存在缓存机制以提高接口性能。缓存值的有效期为5分钟。
 * 注意：由于该接口需要读取/proc/{pid}/smaps_rollup节点信息，耗时较长，建议不要在主线程中直接调用。
 *
 * @param nativeMemInfo 表示指向{@link HiDebug_NativeMemInfo}。函数调用后，若结构体数据为空，则表明调用失败。
 * @param forceRefresh  是否需要无视缓存有效性，强制更新缓存值。\n
 *                      当为true时，直接获取当前内存数据并更新缓存值；\n
 *                      当为false时，缓存有效时，直接返回缓存值，缓存失效时，获取当前内存数据并更新缓存值。
 * @since 20
 */
void OH_HiDebug_GetAppNativeMemInfoWithCache(HiDebug_NativeMemInfo *nativeMemInfo, bool forceRefresh);

/**
 * @brief 获取应用程序进程的内存限制。
 *
 * @param memoryLimit 表示指向{@link HiDebug_MemoryLimit}。
 *        函数调用后，若结构体数据为空，则表明调用失败。
 * @since 12
 */
void OH_HiDebug_GetAppMemoryLimit(HiDebug_MemoryLimit *memoryLimit);

/**
 * @brief 启动应用trace采集。
 *
 * @param flag 采集线程trace方式。
 * @param tags 采集trace场景标签。
 * @param limitSize trace文件的最大大小（以字节为单位），最大为 500MB。
 * @param fileName 输出trace文件名缓冲区。
 * @param length 输出trace文件名缓冲区长度。
 * @return 0 - 成功。\n
 *         {@link HIDEBUG_INVALID_ARGUMENT} 401 - fileName参数为空指针或者传入的length参数过小或者limitSize参数小于等于0。\n
 *         11400102 - 已经开启了一个trace。\n
 *         11400103 - 没有权限去开启trace。\n
 *         11400104 - 系统内部错误。
 * @since 12
 */
HiDebug_ErrorCode OH_HiDebug_StartAppTraceCapture(HiDebug_TraceFlag flag, uint64_t tags, uint32_t limitSize,
    char* fileName, uint32_t length);

/**
 * @brief 停止采集应用程序trace。
 *
 * @return 0 - 成功。\n
 *         11400104 - 系统内部错误。\n
 *         11400105 - 当前没有trace正在运行
 * @since 12
 */
HiDebug_ErrorCode OH_HiDebug_StopAppTraceCapture();

/**
 * @brief 获取应用GPU显存大小。
 * 注意：由于该接口涉及多次跨进程通信，其耗时可能超过1秒，建议不要在主线程中直接调用该接口。
 *
 * @param value 指向用来保存接口获取到的应用显存大小（单位KB）的变量的指针。
 * @return  0 - 接口获取成功。\n
 *          401 - 无效参数，所传递参数为空指针。\n
 *          11400104 - 系统内部错误。
 * @since 14
 */
HiDebug_ErrorCode OH_HiDebug_GetGraphicsMemory(uint32_t *value);

/**
 * @brief 根据给定的fp地址进行栈回溯，该函数异步信号安全。
 *
 * @param object 由{@link OH_HiDebug_CreateBacktraceObject}接口获取到的用来栈回溯的对象。
 * @param startFp 栈回溯的起始栈帧地址。
 * @param pcArray 保存栈回溯得到的pc地址的数组。
 * @param size 保存栈回溯得到的pc地址的数组长度。
 * @return 成功回溯并写入到pcArray中的栈帧数量。如果返回结果为0，原因可能是栈回溯失败。
 * @since 20
 */
int OH_HiDebug_BacktraceFromFp(HiDebug_Backtrace_Object object, void* startFp, void** pcArray, int size);

/**
 * @brief 若{@link OH_HiDebug_SymbolicAddress}接口调用成功，将通过该函数将解析后的栈信息返回给调用者。
 * 注意：由于该接口涉及多次IO操作，耗时较长，建议不要在主线程中直接调用。
 *
 * @param pc 传入{@link OH_HiDebug_SymbolicAddress}接口的需要解析的pc地址。
 * @param arg 传入{@link OH_HiDebug_SymbolicAddress}接口的arg值。
 * @param frame 由传入{@link OH_HiDebug_SymbolicAddress}接口的pc地址解析后的得到栈信息{@link HiDebug_StackFrame}指针，该指针指向内容仅在该函数作用域内有效。
 * @since 20
 */
typedef void (*OH_HiDebug_SymbolicAddressCallback)(void* pc, void* arg, const HiDebug_StackFrame* frame);

/**
 * @brief 通过给定的pc地址获取详细的符号信息，该函数非异步信号安全。
 *
 * @param object 由{@link OH_HiDebug_CreateBacktraceObject}接口创建的对象。
 * @param pc 由{@link OH_HiDebug_BacktraceFromFp}接口获取到的pc地址。
 * @param arg 保留的自定义参数，符号解析成功后系统内部会将该参数传递给回调函数{@link OH_HiDebug_SymbolicAddressCallback}。
 * @param callback 用于返回解析后栈信息的回调函数。
 * @return 返回结果具体可参考{@link HiDebug_ErrorCode}：
 *         {@link HIDEBUG_SUCCESS} 成功获取到详细的栈信息，且该函数传入的callback被调用。\n
 *         {@link HIDEBUG_INVALID_ARGUMENT} 无效参数。\n
 *         {@link HIDEBUG_INVALID_SYMBOLIC_PC_ADDRESS} 无法根据传入的pc地址找到对应的符号。
 * @since 20
 */
HiDebug_ErrorCode OH_HiDebug_SymbolicAddress(HiDebug_Backtrace_Object object, void* pc, void* arg,
    OH_HiDebug_SymbolicAddressCallback callback);

/**
 * @brief 创建一个用于栈回溯及栈解析的对象，该函数非异步信号安全。
 *
 * @return 返回创建的对象的指针，当创建失败时返回NULL。
 * @since 20
 */
HiDebug_Backtrace_Object OH_HiDebug_CreateBacktraceObject(void);

/**
 * @brief 销毁由{@link OH_HiDebug_CreateBacktraceObject}创建的对象，以释放栈回溯及栈解析过程中申请的资源，该函数非异步信号安全。
 *
 * @param object 需要被销毁的对象。
 * @since 20
 */
void OH_HiDebug_DestroyBacktraceObject(HiDebug_Backtrace_Object object);

/**
 * @brief 设置基础库C库MallocDispatch表，用于替换开发者自定义的内存操作函数（例如：malloc/free/calloc/realloc/mmap/munmap)。
 * MallocDispatch表是基础库C库中封装malloc/calloc/realloc/free等内存操作函数的结构体。HiDebug_MallocDispatch只是MallocDispatch结构体的一部分。
 * @param dispatchTable 指向开发者自定义内存操作函数{@link HiDebug_MallocDispatch}结构体指针。
 * @return 返回结果具体可参考{@link HiDebug_ErrorCode}：
 *         {@link HIDEBUG_SUCCESS} 成功设置自定义内存操作函数。
 *         {@link HIDEBUG_INVALID_ARGUMENT} 无效参数。
 * @since 20
 */
HiDebug_ErrorCode OH_HiDebug_SetMallocDispatchTable(struct HiDebug_MallocDispatch *dispatchTable);

/**
 * @brief 获取基础库C库当前默认MallocDispatch表，调用{@link OH_HiDebug_RestoreMallocDispatchTable}可恢复。
 *
 * @return  当前C库默认的{@link HiDebug_MallocDispatch}结构体指针。

 * @since 20
 */
HiDebug_MallocDispatch* OH_HiDebug_GetDefaultMallocDispatchTable(void);

/**
 * @brief 恢复基础库C库MallocDispatch表。
 *
 * @since 20
 */
void OH_HiDebug_RestoreMallocDispatchTable(void);

/**
 * @brief 获取应用显存占用的详细数据。
 *
 * @param interval 当显存数据缓存值存在时间超过设定间隔interval（单位：秒）时，接口会获取最新的显存数据并更新缓存；否则，接口将直接返回缓存值。\n
 * interval的取值范围为[2，3600]，若传入的interval超出取值范围时，将使用300作为默认值。
 * @param summary 表示指向{@link HiDebug_GraphicsMemorySummary}的指针。
 * @return 返回结果具体可参考{@link HiDebug_ErrorCode}：
 *         {@link HIDEBUG_SUCCESS} 成功获取到应用显存数据。\n
 *         {@link HIDEBUG_INVALID_ARGUMENT} 无效参数。\n
 *         {@link HIDEBUG_TRACE_ABNORMAL} 系统内部错误。
 * @since 21
 */
HiDebug_ErrorCode OH_HiDebug_GetGraphicsMemorySummary(uint32_t interval, HiDebug_GraphicsMemorySummary *summary);

#ifdef __cplusplus
}
#endif
/** @} */

#endif // HIVIEWDFX_HIDEBUG_H